/**
   EMMA = Estación Meteorológica de Muestreo Automática
 
 emma_project
 Copyright (C) 2015  Rodrigo Garcia

 This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "dht11.h"

char dht11_init(void)
{
  //  DHT11_DDR &= ~(1<<DHT11_WIRE); // pull up will put to VCC
  DHT11_DDR |= 1<<DHT11_WIRE;
  DHT11_HIGH(); // internal pullup
  unsigned char i = 0;
  // tries to initialize dht11
  for(i=0 ; i<4 ; i++)
    {
      if(!dht11_read())
	{// success reading data
	  dht11_enable();
	  return 0;
	}
      _delay_ms(50);
    }
  // fails to initialize
  return DHT11_ERROR;
}

void dht11_enable(void)
{
  // EEPROM flags
  SetEEPROMFlag(TEMPERATURE_CTRL_BYTE1, DHT11);
  // sets the status flag (sensor working)
  SetRegister(&temperature_stat, DHT11); 
  SetRegister(&relative_humidity_stat, DHT11);
  
  UpdateFlagsFromEEPROM();
}

void dht11_disable(void)
{
  ClearEEPROMFlag(TEMPERATURE_CTRL_BYTE1, DHT11);
  UpdateFlagsFromEEPROM();
}

unsigned char dht11_read(void)
{
  dht11_temperature = SENSOR_NO_ANSWER;
  dht11_RelativeHumidity = SENSOR_NO_ANSWER;

  uint8_t bits[5];
  bits[0]=0;   bits[1]=0;   bits[2]=0;   bits[3]=0;   bits[4]=0; 
  unsigned char i,j = 0;

  //reset port
  DHT11_DDR |= (1<<DHT11_WIRE); // output
  DHT11_HIGH();
  _delay_ms(100);
  
  //send request
  DHT11_LOW();
  _delay_ms(18);
  DHT11_HIGH();
  _delay_us(1);
  DHT11_DDR &= ~(1<<DHT11_WIRE); // input
  _delay_us(39);
  
  //check start condition 1
  if((DHT11_PIN & (1<<DHT11_WIRE)))
    return DHT11_ERROR;
  _delay_us(80);
  //check start condition 2
  if(!(DHT11_PIN & (1<<DHT11_WIRE))) 
    return DHT11_ERROR;
  _delay_us(80);

  //read the data
  for (j=0; j<5; j++)
    { //read 5 bytes |RH_int|RH_decimal|T_int|T_decimal|CHECKSUM|
      uint8_t result=0;
      for(i=0; i<8; i++) //read every bit
	{
	  while(!(DHT11_PIN & (1<<DHT11_WIRE))); //wait for an high input FIXME: exit if no answer and clear status flag
	  _delay_us(30);
	  if(DHT11_PIN & (1<<DHT11_WIRE)) //if input is high after 30 us, get result
	    result |= (1<<(7-i));
	  while(DHT11_PIN & (1<<DHT11_WIRE));  //wait until input get low FIXME: exit if no answer and clear status flag

	}
      bits[j] = result;
    }

  //reset port
  DHT11_DDR |= (1<<DHT11_WIRE); //output
  DHT11_PORT |= (1<<DHT11_WIRE); //low
  _delay_ms(100);
  
  // checksum
  if((bits[0] + bits[1] + bits[2] + bits[3]) == bits[4])
    {
      dht11_RelativeHumidity = bits[0] + (float)(bits[1]/100);
      dht11_temperature = bits[2] + (float)(bits[3]/100);
      return 0;      
    }
  else
    return DHT11_ERROR;
}

float dht11_get_Temperature(void)
{
  dht11_read();
  return dht11_temperature;
}

float dht11_get_RelativeHumidity(void)
{
  dht11_read();
  return dht11_RelativeHumidity;
}

unsigned char dht11_NameIndex(void)
{
  return DHT11;
}

unsigned char dht11_PhysicalPhenIndex(void)
{ // FIXME: this sensor can measure more than 1 physicall phenomenon
  return TEMPERATURE;
}
